/*
* 文件：FFmpegTool.cs
* 作者：王阳
* 时间：2019-5-20
* 描述：
*/
//#define ENABLED
using System.IO;

namespace UnityX
{
#if UNITY_EDITOR == false && ENABLED == false
    [System.Obsolete("FFmpeg功能未启用，请从UnityX窗口勾选：启用FFmpeg功能", true)]
#endif
    public class FFmpegTool
    {
        //-f dshow -i audio="virtual-audio-capturer" 参数 设置了 桌面视频画面 为 输入设备
        //-f dshow -i video="screen-capture-recorder" 参数 设置了 系统声音 为 输入设备

        //public string f = "gdigrab";//输入设备框架:gdigrab,dshow,image2
        //public string c_v = "libx264";//编码器:mpeg4,libx264,libx265
        //public string pix_fmt = "yuv420p";//像素格式:yuv444p,yuv422p,yuv420p
        //public string profile_v = "baseline";//H.264有四种画质级别:baseline,extended,main,high
        //public string q_v = "1";

        public static FFmpeg 转码(string inPath, string outPath, FFmpeg编码格式 编码格式, FFmpeg像素格式 像素格式, int 码率)
        {
            inPath = Path.GetFullPath(inPath);
            outPath = Path.GetFullPath(outPath);
            if (File.Exists(outPath))
            {
                File.Delete(outPath);
            }
            string command = $"-i \"{inPath}\"{GetString(编码格式)}{GetString(像素格式)} -b:v {码率}M -auto-alt-ref 0 \"{outPath}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg 截取(string inPath, string outPath, double 开始时间, double 时长)
        {
            //ffmpeg -ss 00:00:15 -t 00:00:05 -i input.mp4 -vcodec copy -acodec copy output.mp4
            inPath = Path.GetFullPath(inPath);
            outPath = Path.GetFullPath(outPath);
            if (File.Exists(outPath))
            {
                File.Delete(outPath);
            }
            string command = $"-ss {开始时间} -t {时长} -i \"{inPath}\" -c copy \"{outPath}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg 截取末尾(string inPath, string outPath, double 时长)
        {
            //ffmpeg -sseof -3 -i input.mp4 -c copy output.mp4
            inPath = Path.GetFullPath(inPath);
            outPath = Path.GetFullPath(outPath);
            if (File.Exists(outPath))
            {
                File.Delete(outPath);
            }
            string command = $"-sseof {-时长} -i \"{inPath}\" -c copy \"{outPath}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg 图片合成视频(string inDirectory, string outPath, FFmpeg编码格式 编码格式, FFmpeg像素格式 像素格式, int 帧率, int 码率)
        {
            string[] filePaths = Directory.GetFiles(inDirectory);
            if (filePaths.Length == 0)
            {
                return null;
            }
            string extension = Path.GetExtension(filePaths[0]).ToLower();
            string tempDirectory = Path.GetFullPath(Path.GetDirectoryName(outPath) + "/FFmpegTemp");
            string inPath;
            switch (extension)
            {
                case ".jpg":
                    inPath = Path.GetFullPath(tempDirectory + "/unityx.jpg").Replace("unityx.jpg", "%d.jpg");
                    break;
                case ".jpeg":
                    inPath = Path.GetFullPath(tempDirectory + "/unityx.jpeg").Replace("unityx.jpeg", "%d.jpeg");
                    break;
                case ".png":
                    inPath = Path.GetFullPath(tempDirectory + "/unityx.png").Replace("unityx.png", "%d.png");
                    break;
                case ".bmp":
                    inPath = Path.GetFullPath(tempDirectory + "/unityx.bmp").Replace("unityx.bmp", "%d.bmp");
                    break;
                default:
                    return null;
            }
            if (Directory.Exists(tempDirectory))
            {
                Directory.Delete(tempDirectory);
            }
            Directory.CreateDirectory(tempDirectory);
            for (int i = 0; i < filePaths.Length; i++)
            {
                File.Copy(filePaths[i], tempDirectory + "/" + i + extension);
            }
            outPath = Path.GetFullPath(outPath);
            if (File.Exists(outPath))
            {
                File.Delete(outPath);
            }
            //-f image2：明确指定输入为图片序列
            string command = $"-f image2 -r {帧率} -i \"{inPath}\"{GetString(编码格式)}{GetString(像素格式)} -b:v {码率}M -auto-alt-ref 0 \"{outPath}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg RecordScreen(string path, int frameRate = 60, FFmpeg编码格式 编码格式 = FFmpeg编码格式.libx264, FFmpeg像素格式 像素格式 = FFmpeg像素格式.yuv420p)
        {
            if (File.Exists(path))
                File.Delete(path);
            string profile_v = "baseline";//H.264有四种画质级别:baseline,extended,main,high
            string command = $"-f gdigrab -i desktop -r {frameRate}{GetString(编码格式)}{GetString(像素格式)} -profile:v {profile_v} \"{path}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg RecordScreenAndSpeaker(string path, int frameRate = 60, FFmpeg编码格式 编码格式 = FFmpeg编码格式.libx264, FFmpeg像素格式 像素格式 = FFmpeg像素格式.yuv420p)
        {
            if (File.Exists(path))
                File.Delete(path);
            string profile_v = "baseline";//H.264有四种画质级别:baseline,extended,main,high
            string command = $"-f dshow -i video=\"screen-capture-recorder\" -f dshow -i audio=\"virtual-audio-capturer\" -r {frameRate}{GetString(编码格式)}{GetString(像素格式)} -profile:v {profile_v} \"{path}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg RecordWebCam(string webCamName, int duplicateNameIndex, string path, int width, int height, int frameRate = 60, FFmpeg编码格式 编码格式 = FFmpeg编码格式.libx264, FFmpeg像素格式 像素格式 = FFmpeg像素格式.yuv420p)
        {
            if (File.Exists(path))
                File.Delete(path);
            string profile_v = "baseline";//H.264有四种画质级别:baseline,extended,main,high
            string command = $"-f dshow -video_device_number {duplicateNameIndex} -i video=\"{webCamName}\" -s {width}x{height} -r {frameRate}{GetString(编码格式)}{GetString(像素格式)} -profile:v {profile_v} \"{path}\"";
            return new FFmpeg(command);
        }
        public static FFmpeg RecordWebCamAndMicrophone(string webCamName, int duplicateNameIndex, string microphoneName, string path, int width, int height, int frameRate = 60, FFmpeg编码格式 编码格式 = FFmpeg编码格式.libx264, FFmpeg像素格式 像素格式 = FFmpeg像素格式.yuv420p)
        {
            if (File.Exists(path))
                File.Delete(path);
            string profile_v = "baseline";//H.264有四种画质级别:baseline,extended,main,high
            string command = $"-f dshow -video_device_number {duplicateNameIndex} -i video=\"{webCamName}\" -f dshow -i audio=\"{microphoneName}\" -s {width}x{height} -r {frameRate}{GetString(编码格式)}{GetString(像素格式)} -profile:v {profile_v} \"{path}\"";
            return new FFmpeg(command);
        }

        private static string GetString(FFmpeg编码格式 编码格式)
        {
            switch (编码格式)
            {
                case FFmpeg编码格式.Default:
                    return "";
                case FFmpeg编码格式.mpeg4:
                    return " -c:v mpeg4";
                case FFmpeg编码格式.libx264:
                    return " -c:v libx264";
                case FFmpeg编码格式.libx265:
                    return " -c:v libx265";
                case FFmpeg编码格式.libvpx:
                    return " -c:v libvpx";
                case FFmpeg编码格式.libvpx_vp9:
                    return " -c:v libvpx-vp9";
                default:
                    return "";
            }
        }
        private static string GetString(FFmpeg像素格式 像素格式)
        {
            switch (像素格式)
            {
                case FFmpeg像素格式.Default:
                    return "";
                case FFmpeg像素格式.yuv420p:
                    return " -pix_fmt yuv420p";
                case FFmpeg像素格式.yuv422p:
                    return " -pix_fmt yuv422p";
                case FFmpeg像素格式.yuv444p:
                    return " -pix_fmt yuv444p";
                case FFmpeg像素格式.yuva420p:
                    return " -pix_fmt yuva420p";
                default:
                    return "";
            }
        }
    }
}